#include "lcd_st7735.h"
#include "font.h"
//屏幕参数
_lcd_dev  lcddev;
//LCD屏幕写指令
void TFT_WRITE_DATA(uint8_t data)
{
	CS_LOW;
	DATA;
	HAL_SPI_Transmit_DMA(&hspi2,&data,1);
	CS_HIGH;

}
//  LCD屏幕写指令
void TFT_WRITE_COMMAND(uint8_t command)
{
	CS_LOW;
	COMMAND;
	HAL_SPI_Transmit_DMA(&hspi2,&command,1);
	CS_HIGH;
}

//  向对应的寄存机写入单个数�?
void TFT_WRITE_REG(uint8_t reg,uint16_t reg_value)
{
	TFT_WRITE_COMMAND(reg);
	TFT_WRITE_DATA(reg_value);


}
// 写入一个16位的数据
void TFT_WRITE_u16_DATA(uint16_t temp)
{

		uint8_t tempBuf[2];
		tempBuf[0] = temp>>8;
		tempBuf[1] = temp;
		CS_LOW ;
		DATA ;
		HAL_SPI_Transmit_DMA(&hspi2,tempBuf, 2);
		CS_HIGH ;
}


//设置开始的坐标，在每次显示的时候，都需要先设置坐标
void set_windows(uint16_t xStar,uint16_t yStar,uint16_t xEnd,uint16_t yEnd)
{
	//根据数据手册，先发送这是x坐标的指令，在跟上x起始坐标，x结束坐标的数据
	//为什么会有一个偏移量，我没有弄明白，可能和硬件有关
	TFT_WRITE_COMMAND(lcddev.setxcmd);
	TFT_WRITE_DATA(0x00);
	TFT_WRITE_DATA(xStar+lcddev.xoffset);
	TFT_WRITE_DATA(0x00);
	TFT_WRITE_DATA(xEnd+lcddev.xoffset);

	TFT_WRITE_COMMAND(lcddev.setycmd);
	TFT_WRITE_DATA(0x00);
	TFT_WRITE_DATA(yStar+lcddev.yoffset);
	TFT_WRITE_DATA(0x00);
	TFT_WRITE_DATA(yEnd+lcddev.yoffset);
	//等设置完了坐标，发送0x2c指令，开始发送数据
	TFT_WRITE_COMMAND(0X2C);
}

// 清屏函数 ，参数为填入的颜色
void lcd_clear(uint16_t color)
{
	uint16_t i,m;
	set_windows(0,0,lcddev.width-1,lcddev.height-1);
	DATA;
	CS_LOW;

	for(i=0;i<lcddev.height;i++)
		{
	    for(m=0;m<lcddev.width;m++)
	    {
	    	TFT_WRITE_u16_DATA(color);
			}
		}
	CS_HIGH;
}
//设置方向 默认为横屏幕
void  lcd_set_direction()
{
	lcddev.setxcmd=0x2a;
	lcddev.setycmd=0x2b;
	lcddev.wramcmd=0x2C;
	lcddev.width=128;
	lcddev.height=128;
	lcddev.xoffset=2;
	lcddev.yoffset=3;

}
void tft_init()
{

	reset_low;
	HAL_Delay(100);
	reset_high;
	HAL_Delay(100);

	//根据数据手册，对应的寄存器写入对应的值，所以在发送完指令之后，就要发送对应的数据
	TFT_WRITE_COMMAND(0x11);//Sleep exit
	HAL_Delay(120);
		//ST7735R Frame Rate
	TFT_WRITE_COMMAND(0xB1);
	TFT_WRITE_DATA(0x01);
	TFT_WRITE_DATA(0x2C);
	TFT_WRITE_DATA(0x2D);

	TFT_WRITE_COMMAND(0xB2);
	TFT_WRITE_DATA(0x01);
	TFT_WRITE_DATA(0x2C);
	TFT_WRITE_DATA(0x2D);


	TFT_WRITE_COMMAND(0xB3);
	TFT_WRITE_DATA(0x01);
	TFT_WRITE_DATA(0x2C);
	TFT_WRITE_DATA(0x2D);
	TFT_WRITE_DATA(0x01);
	TFT_WRITE_DATA(0x2C);
	TFT_WRITE_DATA(0x2D);

	TFT_WRITE_COMMAND(0xB4); //Column inversion
	TFT_WRITE_DATA(0x07);


	//ST7735R Power Sequence
	TFT_WRITE_COMMAND(0xC0);
	TFT_WRITE_DATA(0xA2);
	TFT_WRITE_DATA(0x02);
	TFT_WRITE_DATA(0x84);
	TFT_WRITE_COMMAND(0xC1);
	TFT_WRITE_DATA(0xC5);


	TFT_WRITE_COMMAND(0xC2);
	TFT_WRITE_DATA(0x0A);
	TFT_WRITE_DATA(0x00);


	TFT_WRITE_COMMAND(0xC3);
	TFT_WRITE_DATA(0x8A);
	TFT_WRITE_DATA(0x2A);
	TFT_WRITE_COMMAND(0xC4);
	TFT_WRITE_DATA(0x8A);
	TFT_WRITE_DATA(0xEE);

	TFT_WRITE_COMMAND(0xC5); //VCOM
	TFT_WRITE_DATA(0x0E);


	TFT_WRITE_COMMAND(0x36); //MX, MY, RGB mode
	TFT_WRITE_DATA(0xC8);



	//ST7735R Gamma Sequence
	TFT_WRITE_COMMAND(0xe0);
	TFT_WRITE_DATA(0x0F);
	TFT_WRITE_DATA(0x1A);
	TFT_WRITE_DATA(0x0F);
	TFT_WRITE_DATA(0x18);
	TFT_WRITE_DATA(0x2F);
	TFT_WRITE_DATA(0x28);


	TFT_WRITE_DATA(0x20);
	TFT_WRITE_DATA(0x22);
	TFT_WRITE_DATA(0x1F);

	TFT_WRITE_DATA(0x1B);
	TFT_WRITE_DATA(0x23);
	TFT_WRITE_DATA(0x37);


	TFT_WRITE_DATA(0x00);

	TFT_WRITE_DATA(0x07);
	TFT_WRITE_DATA(0x02);
	TFT_WRITE_DATA(0x10);


	TFT_WRITE_COMMAND(0xe1);
	TFT_WRITE_DATA(0x0F);
	TFT_WRITE_DATA(0x1B);
	TFT_WRITE_DATA(0x0F);

	TFT_WRITE_DATA(0x17);



	TFT_WRITE_DATA(0x33);
	TFT_WRITE_DATA(0x2C);

	TFT_WRITE_DATA(0x29);

	TFT_WRITE_DATA(0x2E);
	TFT_WRITE_DATA(0x28);
	TFT_WRITE_DATA(0x30);


	TFT_WRITE_DATA(0x30);

	TFT_WRITE_DATA(0x39);
	TFT_WRITE_DATA(0x3F);

	TFT_WRITE_DATA(0x00);
	TFT_WRITE_DATA(0x07);
	TFT_WRITE_DATA(0x03);
	TFT_WRITE_DATA(0x10);

	//设置为了 RGB 5-6-5  65k颜色mode
	TFT_WRITE_COMMAND(0x2A); //65k mode
	TFT_WRITE_DATA(0x00);
	TFT_WRITE_DATA(0x00);
	TFT_WRITE_DATA(0x00);
	TFT_WRITE_DATA(0x7F);

	TFT_WRITE_COMMAND(0x2B); //65k mode
	TFT_WRITE_DATA(0x00);
	TFT_WRITE_DATA(0x00);
	TFT_WRITE_DATA(0x00);
	TFT_WRITE_DATA(0x9F);

	TFT_WRITE_COMMAND(0xF0); //65k mode
	TFT_WRITE_DATA(0x01);
	TFT_WRITE_COMMAND(0xF6); //65k mode
	TFT_WRITE_DATA(0x00);


	TFT_WRITE_COMMAND(0x3A); //这个指令将屏幕设置为了 65k颜色模式
	TFT_WRITE_DATA(0x05);
	TFT_WRITE_COMMAND(0x29);//Display on
	lcd_set_direction();

	TFT_WRITE_REG(0x36,(1<<3)|(1<<6)|(1<<7)); //这个指令很关键，控制了屏幕的显示方向等参数

	TFT_WRITE_COMMAND(0xc0);//Display on  TFT_WRITE_COMMAND(0x36  );设置�?始坐�?
	TFT_WRITE_DATA(0x0A);

	lcd_clear(0xffe0);
	led_high;
}
void draw_point(uint16_t x,uint16_t y,uint16_t color)
{
	set_windows(x,y,x,y);
	TFT_WRITE_u16_DATA(color);
}
/**
 * @brief		显示一个ASCII码字符,横纵坐标不要越界，否则会不显示
 * @param   x,y		显示起始坐标
 * @param   ch		需要显示的字符
 * @param   size	字体大小(支持16/24/32号字体)
 * @return  none
 * @note		需要font.h字库文件的支持
 */
void TFT_ShowChar(uint16_t x, uint16_t y, char ch, uint16_t back_color, uint16_t font_color, uint8_t font_size)
{
	int i = 0, j = 0;
	uint8_t temp = 0;
	uint8_t size = 0;
	uint8_t t = 0;

	/* 检测显示是否会越界 */
	 if((x > (LCD_Width - font_size / 2)) || (y > (LCD_Height - font_size)))
		 return;

	/* 根据字符大小设置显存操作区域 */
	 set_windows(x, y, x + font_size/2 - 1, y + font_size - 1);

	 /* 计算字符在字库中的偏移值*/
	 ch = ch - ' ';

	 /* 显示16号/32号字体 */
	 if((font_size == 16) || (font_size == 32) )
	 {
		  /* 计算字体一个字符对应点阵集所占的字节数 */
 			size = (font_size / 8 + ((font_size % 8) ? 1 : 0)) * (font_size / 2);

			for(i = 0; i < size; i++)
			{
					if(font_size == 16)
						temp = asc2_1608[ch][i];	//调用1608字体  将16*16的字库进行了注释 ，此处进行修改
					else if(font_size == 32)
							temp = asc2_3216[ch][i];	//调用3216字体
					else
							return;			//没有的字库

					for(j = 0; j < 8; j++)
					{
							if(temp & 0x80)
								{

									TFT_WRITE_u16_DATA(font_color);
								}
							else
							{

								TFT_WRITE_u16_DATA(back_color);
							}
							temp <<= 1;
					}
			}
	 }
	 // 将12号字体进行了注释
//	  /* 显示12号字体 */
//	 else if(font_size == 12)
//	 {
//		  /* 计算字体一个字符对应点阵集所占的字节数 */
// 			size = (font_size / 8 + ((font_size % 8) ? 1 : 0)) * (font_size / 2);
//
//			for(i = 0; i < size; i++)
//			{
//				  temp = asc2_1206[ch][i];
//
//					for(j = 0; j < 6; j++)
//					{
//							if(temp & 0x80)
//							{
//								LCD_Write_Data_DMA(font_color>>8);
//								LCD_Write_Data_DMA(font_color);
//							}
//							else
//							{
//								LCD_Write_Data_DMA(back_color>>8);
//								LCD_Write_Data_DMA(back_color);
//							}
//
//							temp <<= 1;
//					}
//			}
//	 }
	 /* 显示24号字体 */
	 else if(font_size == 24)
	 {
		  /* 计算字体一个字符对应点阵集所占的字节数 */
 			size = (font_size * 16) / 8;

			for(i = 0; i < size; i++)
			{
				  temp = asc2_2412[ch][i];
					if(i % 2 == 0)
							t = 8;
					else
							t = 4;
					for(j = 0; j < t; j++)
					{
							if(temp & 0x80)
							{

								TFT_WRITE_u16_DATA(font_color);
							}
							else
							{

								TFT_WRITE_u16_DATA(back_color);
							}

							temp <<= 1;
					}
			}
	 }
	 /* 其余字体 */
	 else
		 return;
}
/**
 * @brief		显示一个ASCII码字符串  32号字体（英文和数字），横坐标占据16位
 * @param   x,y		显示起始坐标
 * @param   str		需要显示的字符串
 * @param   size	字体大小(支持16/24/32号字体)
 * @return  none
 * @note		1. 需要font.h字库文件的支持
 * 					2. 超过指定width不显示超过的字符
 */
void LCD_ShowCharStr(uint16_t x, uint16_t y, uint32_t max_width, char* str, uint16_t back_color, uint16_t font_color, uint8_t font_size)
{

	max_width += x;

	while((*str <= '~') && (*str >= ' '))	//判断是否非法字符
	{
			if(x >= max_width)
			{
					//x方向越界，结束
					break;
			}

			TFT_ShowChar(x,y,*str,back_color, font_color,font_size);
			x += font_size / 2;
			str++;
	}
}

/**
 * @brief		显示一个ASCII码数字字符，最多只能一次显示十位
 * @param   x,y		显示起始坐标
 * @param   str		需要显示的字符串
 * @param   size	字体大小(支持16/24/32号字体)
 * @return  none
 * @note		1. 需要font.h字库文件的支持
 * 					2. 超过指定width不显示超过的字符
 */
void LCD_ShowCharNumber(uint16_t x, uint16_t y, uint32_t max_width, uint8_t  number, uint16_t back_color, uint16_t font_color, uint8_t font_size)
{
	char number_ascii[10];
	//调用sprintf将数字转换为ascii码字符

	sprintf(number_ascii,"%d",number);

	LCD_ShowCharStr(x,y,max_width,number_ascii,back_color,font_color,font_size);

}
